package com.ecjtu.stadiumre_servations.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.injector.methods.UpdateById;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ecjtu.stadiumre_servations.entity.domain.Booking;
import com.ecjtu.stadiumre_servations.entity.domain.GroupActivity;
import com.ecjtu.stadiumre_servations.entity.domain.Venue;
import com.ecjtu.stadiumre_servations.entity.dto.VenueDTO;
import com.ecjtu.stadiumre_servations.mapper.BookingMapper;
import com.ecjtu.stadiumre_servations.mapper.GroupActivityMapper;
import com.ecjtu.stadiumre_servations.mapper.VenueMapper;
import com.ecjtu.stadiumre_servations.response.Result;
import com.ecjtu.stadiumre_servations.response.ResultCodeEnum;
import com.ecjtu.stadiumre_servations.service.BookingService;
import com.ecjtu.stadiumre_servations.service.MinioService;
import com.ecjtu.stadiumre_servations.service.VenueService;
import com.ecjtu.stadiumre_servations.utils.LocalDateTimeSplitterUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Service
public class VenueServiceImpl extends ServiceImpl<VenueMapper, Venue> implements VenueService {
    @Autowired
    private BookingMapper bookingMapper;
    @Autowired
    private VenueMapper venueMapper;
    @Autowired
    private BookingService bookingService;
    @Autowired
    private MinioService minioService;
    @Autowired
    private GroupActivityMapper groupActivityMapper;
    @Resource
    private RedisTemplate<String, Venue> redisTemplate;
    @Override
    public Result findAll(Page<Venue> page) {
        return Result.build(venueMapper.selectPage(page, null), ResultCodeEnum.SELECT_SUCCESS);
    }
    @Override
    public Result findByType(Page<Venue> page, String venueType) {
        QueryWrapper<Venue> queryWrapper = new QueryWrapper<>();
        // 根据场地类型进行查询
        if (venueType != null && !venueType.trim().isEmpty()) {
            queryWrapper.like("venue_type", venueType);
        }
        return Result.build(venueMapper.selectPage(page, queryWrapper), ResultCodeEnum.SELECT_SUCCESS);
//        return Result.ok().message("");
    }
    @Override
    public Result findByName(Page<Venue> page, String venueName) {
        QueryWrapper<Venue> queryWrapper = new QueryWrapper<>();
        // 根据场地名称进行模糊查询
        if (venueName != null && !venueName.trim().isEmpty()) {
            queryWrapper.like("venue_name", venueName);
        }
        return Result.build(venueMapper.selectPage(page, queryWrapper), ResultCodeEnum.SELECT_SUCCESS);
    }
    @Override
    public Result addVenue(@RequestParam VenueDTO venueDTO, MultipartFile imageFile) {
        // 基础参数校验
        if (StringUtils.isBlank(venueDTO.getVenueName())|| StringUtils.isBlank(venueDTO.getVenueType()) ||
                StringUtils.isBlank(venueDTO.getVenueStatus()) || venueDTO.getVenueStartTime() == null || venueDTO.getVenueEndTime() == null ||
                StringUtils.isBlank(venueDTO.getVenueNumber()) || venueDTO.getVenuePrice() == 0
                // venueDTO.getVenuePrice() == 0 的判断不准确 得优化
        ) {
            return Result.fail("必填参数缺失或状态无效");
        }
        if (!venueDTO.getVenueStartTime().isBefore(venueDTO.getVenueEndTime())) {
            return Result.fail("可预约结束时间应大于可预约开始时间");
        }
        // 创建场地实体
        Venue venue = new Venue();
        venue.setVenueId(UUID.randomUUID().toString()); // 使用生成的 UUID

        // 复制基本属性
        venue.setVenueName(venueDTO.getVenueName());
        venue.setVenueType(venueDTO.getVenueType());
        venue.setVenueNumber(venueDTO.getVenueNumber());
        venue.setVenueStatus(venueDTO.getVenueStatus());
        venue.setVenuePrice(venueDTO.getVenuePrice());
        venue.setDescription(venueDTO.getDescription());
        venue.setVenueAddress(venueDTO.getVenueAddress());

        // 处理时间转换：LocalTime -> LocalDateTime
        LocalDate today = LocalDate.now();
        venue.setVenueStartTime(LocalDateTime.of(today, venueDTO.getVenueStartTime()));
        venue.setVenueEndTime(LocalDateTime.of(today, venueDTO.getVenueEndTime()));

        // 处理图片上传
        if (imageFile != null && !imageFile.isEmpty()) {
            Result<String> uploadResult = minioService.uploadFile(imageFile);
            if (uploadResult.getCode() != 200) {
                return Result.fail("图片上传失败: " + uploadResult.getMessage());
            }
            String objectName = uploadResult.getData();
            String pictureAddress = (String) minioService.getFileUrl(objectName).getData();
            venue.setPictureAddress(pictureAddress);
        }
        // 5保存场地信息
        if (save(venue)) {
            return Result.ok("添加场地成功");
        } else {
            return Result.fail("添加场地失败，数据库操作异常");
        }
    }
    /*查看详细
    * */
    @Override
    public Result findById(String id) {
        if (id!=null){
//        String key = "venue:" + id;
//        Venue venue = redisTemplate.opsForValue().get(key);
//        if (venue == null) {
//            venue = venueMapper.selectOne(Wrappers.<Venue>lambdaQuery().eq(Venue::getVenueId, id));
//            if (venue != null) {
//                redisTemplate.opsForValue().set(key, venue, 60, TimeUnit.MINUTES);
//            }
//        }
       return Result.build(venueMapper.selectById(id),ResultCodeEnum.SELECT_SUCCESS);
    }
        return Result.fail("该场地不存在");
    }

    @Override
        public Result deleteVenue(String id) {
            if (id == null) {
                return Result.fail("删除失败，场馆 ID 为空");
            }
            Venue venue = getOne(Wrappers.<Venue>lambdaQuery().eq(Venue::getVenueId, id));
            if (venue == null) {
                return Result.fail("该场馆不存在，删除失败");
            }
            if (bookingService.hasBookings(id)) {
                return Result.fail("该场馆存在预约，不能删除");
            }
            try {
                // 明确使用 venueId 作为主键进行删除
                boolean result = remove(new LambdaQueryWrapper<Venue>().eq(Venue::getVenueId, id));
                if (result) {
                    return Result.ok("删除成功");
                } else {
                    return Result.fail("删除失败，数据库操作异常");
                }
            } catch (Exception e) {
                e.printStackTrace();
                return Result.fail("删除失败，数据库操作异常");
            }
        }

    @Override
    public Result updateVenue(String id ,VenueDTO venueDTO) {
        if (id == null) {
            return Result.fail("更新操作需要提供场地编号");
        }
        Venue venue = getOne(Wrappers.<Venue>lambdaQuery().eq(Venue::getVenueId, id));
        if (venue == null) {
            return Result.fail("找不到对应场地记录");
        }
        // 更新基本字段
        if (StringUtils.isNotBlank(venueDTO.getVenueName())) {
            venue.setVenueName(venueDTO.getVenueName());
        }
        if (StringUtils.isNotBlank(venueDTO.getVenueType())) {
            venue.setVenueType(venueDTO.getVenueType());
        }
        if (StringUtils.isNotBlank(venueDTO.getVenueNumber())) {
            venue.setVenueNumber(venueDTO.getVenueNumber());
        }
        if (StringUtils.isNotBlank(venueDTO.getVenueStatus())) {
            venue.setVenueStatus(venueDTO.getVenueStatus());
        }
        if (venueDTO.getVenuePrice() > 0) {
            venue.setVenuePrice(venueDTO.getVenuePrice());
        }
        if (StringUtils.isNotBlank(venueDTO.getDescription())) {
            venue.setDescription(venueDTO.getDescription());
        }
        if (StringUtils.isNotBlank(venueDTO.getVenueAddress())) {
            venue.setVenueAddress(venueDTO.getVenueAddress());
        }

        // 处理时间更新
        if (venueDTO.getVenueStartTime() != null) {
            LocalDate today = LocalDate.now();
            venue.setVenueStartTime(LocalDateTime.of(today, venueDTO.getVenueStartTime()));
        }
        if (venueDTO.getVenueEndTime() != null) {
            LocalDate today = LocalDate.now();
            venue.setVenueEndTime(LocalDateTime.of(today, venueDTO.getVenueEndTime()));
        }

        boolean success = updateById(venue);
        if (!success) {
            return Result.fail("场地更新失败，请稍后重试");
        }
        return Result.ok("修改成功");
    }

    @Override
    public Result findAvailable(Page<Venue> page) {
        LambdaQueryWrapper<Venue> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Venue::getVenueStatus, "可预约");
        return Result.build(venueMapper.selectPage(page, lambdaQueryWrapper), ResultCodeEnum.SELECT_SUCCESS);
    }

    @Override
    public Result getAvailableTimeSlots(String venueId, String date) {
        try {
            // 查询场馆信息
            Venue venue = venueMapper.selectOne(
                    Wrappers.<Venue>lambdaQuery().eq(Venue::getVenueId, venueId)
            );
            if (venue == null) {
                return Result.fail("场馆不存在");
            }

            // 获取场馆开放时间（当天的）
            LocalDate localDate = LocalDate.parse(date); // 例如"2025-07-03"
            LocalDateTime venueStart = localDate.atTime(venue.getVenueStartTime().toLocalTime());
            LocalDateTime venueEnd = localDate.atTime(venue.getVenueEndTime().toLocalTime());

            // 查询该场馆当天的所有有效预约记录（个人预约和拼团预约都排除掉）
            LocalDateTime dayStart = localDate.atStartOfDay();
            LocalDateTime dayEnd = localDate.plusDays(1).atStartOfDay();
            LambdaQueryWrapper<Booking> queryWrapper = Wrappers.<Booking>lambdaQuery()
                    .eq(Booking::getVenueId, venueId)
                    .ge(Booking::getBookingStartTime, dayStart)
                    .lt(Booking::getBookingStartTime, dayEnd)
                    .and(wrapper ->
                            wrapper
                                    // 个人预约
                                    .and(w1 -> w1
                                            .eq(Booking::getBookingType, "个人预约")
                                            .in(Booking::getBookingStatus, "待使用", "已使用", "待支付","已支付")
                                    )
                                    // 拼团预约
                                    .or(w2 -> w2
                                            .eq(Booking::getBookingType, "拼团预约")
                                            .in(Booking::getBookingStatus, "拼团中", "已成团", "进行中", "待支付")
                                    )
                    );
            List<Booking> bookings = bookingMapper.selectList(queryWrapper);
            // 查询该场馆当天的所有有效拼团活动记录（状态要包含拼团中、已成团、进行中等）
            LambdaQueryWrapper<GroupActivity> groupActivityQueryWrapper = Wrappers.<GroupActivity>lambdaQuery()
                    .eq(GroupActivity::getActivityVenueId, venueId)
                    .in(GroupActivity::getActivityStatus, "拼团中", "已成团", "进行中", "未开始")
                    .ge(GroupActivity::getActivityStartTime, dayStart)
                    .lt(GroupActivity::getActivityStartTime, dayEnd);
            List<GroupActivity> groupActivities = groupActivityMapper.selectList(groupActivityQueryWrapper);
            System.out.println("groupActivities: " + groupActivities);

            // 将拼团活动记录转换为类似预约记录的形式，方便统一处理
            List<Booking> allOccupiedSlots = new ArrayList<>(bookings);
            for (GroupActivity groupActivity : groupActivities) {
                Booking mockBooking = new Booking();
                mockBooking.setBookingStartTime(groupActivity.getActivityStartTime());
                mockBooking.setBookingEndTime(groupActivity.getActivityEndTime());
                allOccupiedSlots.add(mockBooking);
            }

            // 计算可用时间段
            List<LocalDateTime[]> availableSlots = calculateAvailableTimeSlots(venueStart, venueEnd, allOccupiedSlots);

            // 封装结果
            return Result.ok(availableSlots);
        } catch (Exception e) {
            log.error("获取可用时间段失败", e);
            return Result.fail("获取可用时间段失败");
        }
    }

    /**
     * 计算场馆可用时间段
     */
    /**
     * 计算场馆可用时间段
     */
    private List<LocalDateTime[]> calculateAvailableTimeSlots(LocalDateTime venueStart,
                                                              LocalDateTime venueEnd,
                                                              List<Booking> bookings) {
        List<LocalDateTime[]> availableSlots = new ArrayList<>();

        // 如果没有预约或拼团活动，整个开放时间都是可用的
        if (bookings.isEmpty()) {
            availableSlots.addAll(LocalDateTimeSplitterUtils.splitIntoHourlyIntervals(venueStart, venueEnd));
            return availableSlots;
        }

        // 按预约开始时间排序
        bookings.sort(Comparator.comparing(Booking::getBookingStartTime));

        // 合并重叠的时间段
        List<Booking> mergedBookings = new ArrayList<>();
        LocalDateTime currentStart = bookings.get(0).getBookingStartTime();
        LocalDateTime currentEnd = bookings.get(0).getBookingEndTime();

        for (int i = 1; i < bookings.size(); i++) {
            Booking booking = bookings.get(i);
            LocalDateTime bookingStart = booking.getBookingStartTime();
            LocalDateTime bookingEnd = booking.getBookingEndTime();

            // 如果当前时间段与下一个时间段重叠，则合并
            if (bookingStart.isBefore(currentEnd)) {
                currentEnd = currentEnd.isAfter(bookingEnd) ? currentEnd : bookingEnd;
            } else {
                // 否则添加当前合并的时间段，并开始新的合并
                Booking mergedBooking = new Booking();
                mergedBooking.setBookingStartTime(currentStart);
                mergedBooking.setBookingEndTime(currentEnd);
                mergedBookings.add(mergedBooking);

                currentStart = bookingStart;
                currentEnd = bookingEnd;
            }
        }

        // 添加最后一个合并的时间段
        Booking lastMergedBooking = new Booking();
        lastMergedBooking.setBookingStartTime(currentStart);
        lastMergedBooking.setBookingEndTime(currentEnd);
        mergedBookings.add(lastMergedBooking);

        // 计算可用时间段
        currentStart = venueStart;

        for (Booking mergedBooking : mergedBookings) {
            LocalDateTime mergedStart = mergedBooking.getBookingStartTime();
            LocalDateTime mergedEnd = mergedBooking.getBookingEndTime();

            // 发现可用时间段
            if (currentStart.isBefore(mergedStart)) {
                availableSlots.addAll(LocalDateTimeSplitterUtils.splitIntoHourlyIntervals(currentStart, mergedStart));
            }

            // 更新当前起始时间为合并后的结束时间
            currentStart = mergedEnd;
        }

        // 处理最后一段可用时间
        if (currentStart.isBefore(venueEnd)) {
            availableSlots.addAll(LocalDateTimeSplitterUtils.splitIntoHourlyIntervals(currentStart, venueEnd));
        }

        return availableSlots;
    }

}

